package MicroSpring.common;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

public class BeanUtils {


    public static void copyProperties(Object source, Object target)  {
        try {
            copyFields(source,target);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static boolean checkLazyBean(Class<?> type) {
        if (AnntationUtils.isAnnotationOfComponent(type)){
            if (AnntationUtils.isPrototype(type))
                return true;
        }
        return false;
    }

    private static void copyMethods(Object source, Object target) {
        Method[] sourceMethods = source.getClass().getDeclaredMethods();
        Method[] targetMethods = target.getClass().getDeclaredMethods();
        for (Method m1 : targetMethods) {
            for (int i = 0; i < sourceMethods.length; i++) {
                if (m1.getReturnType() == sourceMethods[i].getReturnType()
                        && m1.getName().equals(sourceMethods[i].getName())
                        && equalsParameters(m1.getParameters(),sourceMethods[i].getParameters())){

                }
            }
        }
    }

    private static boolean equalsParameters(Parameter[] p1, Parameter[] p2) {
        if (p1.length != p2.length)
            return false;
        int cnt=0;
        for (int i = 0; i < p1.length; i++) {
            for (int j = 0; j < p2.length; j++) {
                if (p1.equals(p2)) {
                    cnt++;
                    continue;
                }
            }
        }
        return cnt==p1.length;
    }

    private static void copyFields(Object source, Object target) throws IllegalAccessException {
        Field[] sourceFields = source.getClass().getDeclaredFields();
        Field[] targetFields = target.getClass().getDeclaredFields();
        for (Field f1 : targetFields) {
            f1.setAccessible(true);
            for (int i = 0; i < sourceFields.length; i++) {
                sourceFields[i].setAccessible(true);
                if (sourceFields[i].get(source) == null)
                    continue;
                if (f1.getType() == sourceFields[i].getType()
                        && f1.getName().equals(sourceFields[i].getName())){
                    f1.set(target,sourceFields[i].get(source));
                }
            }
        }
    }
    /*
        通过get set方法进行复制
     */
    public static void copyPropertiesByMethod(Object source, Object target) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        Map<Method,Method> methodMethodMap=new HashMap<>();
        for (Method dm : sourceClass.getDeclaredMethods()) {
            for (Method dm2 : targetClass.getDeclaredMethods()) {
                String dmName = dm.getName();
                String dm2Name = dm2.getName();
                if (dmName.equals(dm2Name)){
                    if (dmName.startsWith("set")){
                        Method getM = sourceClass.getDeclaredMethod(getGetMethodsName(dmName));
                        if (getM !=null){
                            methodMethodMap.put(dm2,getM);
                        }
                    }
                }

            }
        }
        for (Map.Entry<Method, Method> entry : methodMethodMap.entrySet()) {
            Method setM = entry.getKey();
            Method getM = entry.getValue();
            Object r = getM.invoke(source);
            setM.invoke(target,r);
        }
    }

    private static String getGetMethodsName(String dmName) {
        //通过setXX获得getXX
        return dmName.replaceAll("set","get");
    }

}
